#include <iostream>
#include <string>
#include <typeinfo>
 
struct Base {}; // 非多态
struct Derived : Base {};
 
struct Base2 { 
    virtual void foo() {} 
    virtual void Print() const {}
    }; // 多态

struct DerivedP : Base2 {

    void Print() const final
    {
        std::cout << "final tttttttttt" << " " 
                << typeid(this).name() 
                <<" or tttttttt"<< " " 
                << typeid(*this).name()
                << std::endl;  
    }
};
 
// struct DerivedPP : DerivedP { 
//         void Print() const 
//     {
//         std::cout << "final tttttttttt" << " " 
//                 << typeid(this).name() 
//                 <<" or tttttttt"<< " " 
//                 << typeid(*this).name()
//                 << std::endl;  
//     }
// };

int main()
{
    int myint = 50;
    std::string mystr = "string";
    double *mydoubleptr = nullptr;
    char* charptr = nullptr;
    int*  intptr = nullptr;
 
    std::cout << "myint 的类型：" << typeid(myint).name() << '\n'
              << "mystr 的类型：" << typeid(mystr).name() << '\n'
              << "mydoubleptr 的类型：" << typeid(mydoubleptr).name() << '\n'
              << "char* 的类型：" << typeid(charptr).name() << '\n'
              << "int* 的类型：" << typeid(intptr).name() << '\n';
 
    // std::cout << myint 是多态类型的泛左值表达式；求值
    const std::type_info& r1 = typeid(std::cout << myint);
    std::cout << '\n' << "std::cout<<myint 的类型：" << r1.name() << '\n';
 
    // std::printf() 不是多态类型的泛左值表达式；不求值
    const std::type_info& r2 = typeid(std::printf("%d\n", myint));
    std::cout << "printf(\"%d\\n\",myint) 的类型：" << r2.name() << '\n';
 
    // 非多态左值时是静态类型
    Derived d1;
    Base& b1 = d1;
    std::cout << "非多态基类的引用：" << typeid(b1).name() << '\n';
 
    DerivedP d2;
    Base2& b2 = d2;
    std::cout << "多态基类的引用：" << typeid(b2).name() << '\n';
    // std::cout << "多态基类的引用：" << typeid(*this).name() << '\n';
    d2.Print();
    try
    {
        // 解引用空指针：对于非多态表达式 OK
        std::cout << "mydoubleptr 指向 " << typeid(*mydoubleptr).name() << '\n'; 
        // 解引用空指针：对多态左值则不行
        DerivedP* bad_ptr = nullptr;
        std::cout << "bad_ptr 指向...";
        std::cout << typeid(*bad_ptr).name() << '\n';
    }
    catch (const std::bad_typeid& e)
    {
         std::cout << " 捕获 " << e.what() << '\n';
    }
}